package com.bootdo.system.controller;

import com.bootdo.common.annotation.Log;
import com.bootdo.common.config.BootdoConfig;
import com.bootdo.common.controller.BaseController;
import com.bootdo.common.utils.FileUtil;
import com.bootdo.common.utils.R;
import com.bootdo.system.domain.DataBaseLogDO;
import com.bootdo.system.domain.SetDO;
import com.bootdo.system.domain.UserDO;
import com.bootdo.system.service.SetService;
import com.bootdo.system.service.UserService;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@RequestMapping("/sys/set")
@Controller
public class SetController extends BaseController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private String prefix="system/set"  ;

    @RequiresPermissions("sys:sysSet:sysSet")
    @GetMapping("")
    String user(Model model) {
        return prefix + "/sysSet";
    }

    @Autowired
    private SetService setService;

    @Autowired
    private BootdoConfig bootdoConfig;

    @Autowired
    private UserService userService;

    @ApiOperation(value="获取系统设置开关", notes="")
    @ResponseBody
    @PostMapping("/list")
    @RequiresPermissions("sys:sysSet:sysSet")
    public R list() {
        Map<String,Object> map = new HashMap<String, Object>();
        List<SetDO> setDOList = setService.list(null);
        //获取配置文件地址
        String synchroPath = bootdoConfig.getSynchroPath();
        //读取配置文件里面的文件信息
        Properties properties = new Properties();
        // 使用InPutStream流读取properties文件
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(synchroPath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            properties.load(bufferedReader);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取同步服务器ip地址
        String synchroIp = properties.getProperty("synchroIp");
        //获取同步服务器port端口号
        String synchroPort = properties.getProperty("synchroPort");
        //版本号
        String version = bootdoConfig.getVersion();
        map.put("setDOList",setDOList);
        map.put("synchroIp",synchroIp);
        map.put("synchroPort",synchroPort);
        map.put("version",version);
        return R.ok().put("map",map);
    }

    /**
     * 修改
     */
    @Log("审批设置开关")
    @ResponseBody
    @RequestMapping("/update")
    @RequiresPermissions("system:sysSet:update")
    public R update(SetDO setDO) {
        if (setService.update(setDO) > 0) {
            return R.ok();
        }
        return R.error();
    }

    /**
     * 修改ip和端口
     */
    @Log("修改ip和端口")
    @ResponseBody
    @RequestMapping("/updateProperties")
    @RequiresPermissions("system:sysSet:update")
    public R updatePort(String synchroIp,String synchroPort) {
        //获取配置文件地址
        String synchroPath = bootdoConfig.getSynchroPath();
        //读取配置文件里面的文件信息
        Properties properties = new Properties();
        properties.setProperty("synchroIp", synchroIp);
        properties.setProperty("synchroPort", synchroPort);
        properties.setProperty("synchroTime", "15");
        FileOutputStream oFile = null;
        try {
            oFile = new FileOutputStream(synchroPath);
            //将Properties中的属性列表（键和元素对）写入输出流
            properties.store(oFile, "");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                oFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //获取同步服务器ip地址
        DriverManagerDataSource dataSource=new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://" + synchroIp + ":" + bootdoConfig.getRemoteDataBasePort() + "/" + bootdoConfig.getRemoteDataBaseName());
        dataSource.setUsername(bootdoConfig.getRemoteDataBaseUser());
        dataSource.setPassword(bootdoConfig.getRemoteDataBasePassword());

        JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);

        //数据源信息同步
        String sql = "show master status";
        List<DataBaseLogDO> list = jdbcTemplate.query(sql, new RowMapper() {
            @Override
            public Object mapRow(ResultSet resultSet, int i) throws SQLException {
                DataBaseLogDO dataBaseLogDO = new DataBaseLogDO();
                dataBaseLogDO.setFile(resultSet.getString("File"));
                dataBaseLogDO.setPosition(resultSet.getString("Position"));
                return dataBaseLogDO;
            }
        });
        if(!CollectionUtils.isEmpty(list)) {
            DataBaseLogDO dataBaseLogDO = list.get(0);

            dataSource.setUrl("jdbc:mysql://" + bootdoConfig.getLocalDataBaseIp() + ":" + bootdoConfig.getRemoteDataBasePort() + "/" + bootdoConfig.getRemoteDataBaseName());
            String logPath = bootdoConfig.getLogPath();
            String logLocation = bootdoConfig.getLogLocation();

            jdbcTemplate=new JdbcTemplate(dataSource);
            //文件同步日志记录
            sql = "stop slave";
            jdbcTemplate.execute(sql);
            FileUtil.writeFile(sql + ";", logPath, logLocation);
            //数据库主从复制
            try {
                sql = "CHANGE MASTER TO MASTER_HOST='"+ synchroIp +"', MASTER_PORT=" + bootdoConfig.getRemoteDataBasePort() + "," +
                        "MASTER_USER='"+ bootdoConfig.getRemoteDataBaseUser() +"'," +
                        "MASTER_PASSWORD='"+ bootdoConfig.getRemoteDataBasePassword() +"'," +
                        "MASTER_LOG_FILE='"+ dataBaseLogDO.getFile() +"'," +
                        "MASTER_LOG_POS="+ dataBaseLogDO.getPosition();
                jdbcTemplate.execute(sql);
                FileUtil.writeFile(sql + ";", logPath, logLocation);
                logger.info("数据库执行同步语句成功，语句为：" + sql);
            }catch (Exception e) {
                logger.info("数据库执行同步语句失败，语句为：" + sql);
                logger.error(e.getMessage(),e);
                return R.error("数据库执行同步语句失败，语句为：" + sql);
            }
            sql = "start slave";
            jdbcTemplate.execute(sql);
            FileUtil.writeFile(sql + ";", logPath, logLocation);
        }
        return R.ok();
    }

    @GetMapping("/add/{type}")
    @RequiresPermissions("system:sysSet:add")
    String add(@PathVariable("type") String type, Model model) {
        model.addAttribute("type", type);
        return  prefix + "/add";
    }

    /**
     * 保存
     */
    @Log("审批设置添加")
    @ResponseBody
    @PostMapping("/save")
    @RequiresPermissions("system:sysSet:add")
    public R save(SetDO setDO) {
        List<SetDO> setDOList = setService.list(setDO.getSetCode());
        for(SetDO set:setDOList){
            if (set.getSetValue().equals(setDO.getSetValue())) {
                return R.error(1, "该文件类型已添加");
            }
        }
        if (setService.save(setDO) > 0) {
            return R.ok();
        }
        return R.error();
    }

    /**
     * 删除
     */
    @Log("审批设置删除")
    @PostMapping("/remove")
    @ResponseBody
    @RequiresPermissions("system:sysSet:remove")
    public R remove(Long id) {
        if (setService.remove(id) > 0) {
            return R.ok();
        }
        return R.error();
    }

    /**
     * 获取参数对应的值
     * @param type
     * @return
     */
    @PostMapping("/getSetValue")
    @ResponseBody
    SetDO getSetValue(String type) {
        SetDO setDO = setService.get(type);
        return setDO;
    }

}
